package com.elitel.frame.business.aspect;

import com.alibaba.fastjson.JSONObject;
import com.elitel.frame.base.service.SysPrjServiceService;
import com.elitel.frame.main.entity.SysPrjservice;
import com.elitel.frame.main.entity.vo.JsonDataResult;
import com.elitel.frame.main.entity.vo.PageResponseVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import static com.elitel.common.constant.SYS_CONST.TASK_PARAM;
import static com.elitel.common.core.constant.RequestConstant.APP_CODE;
import static com.elitel.common.core.constant.RequestConstant.SERVICE_ID;
import static com.elitel.frame.business.service.impl.PolymerServerServiceImpl.POLYMER;
import static com.elitel.frame.business.service.impl.PolymerServerServiceImpl.POLYMER_PARAM;
import static com.elitel.frame.main.entity.constant.CommonApiUrl.COMMON_API;
import static com.elitel.frame.main.entity.constant.CommonApiUrl.JSON_COMMON_API;

@Aspect
@Component
@ConfigurationProperties(prefix = "req.log")
public class SysReqLogAspect {

    private String url;

    @Resource
    private SysPrjServiceService sysPrjServiceService;

    public void setUrl(String url) {
        this.url = url;
    }

    @Pointcut("execution(* com.elitel.frame.business.controller.*.*(..))")
    public void log() {
    }

    @Around("log()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        long start = System.currentTimeMillis();
        Object result = null;
        String errorMsg = null;
        try {
            result = joinPoint.proceed(args);
        } catch (Exception e) {
            errorMsg = e.getMessage();
            throw e;
        } finally {
            if (result instanceof JsonDataResult) {
                JsonDataResult jsonDataResult = (JsonDataResult) result;
                Object data = jsonDataResult.getData();
                if (data instanceof PageResponseVo) {
                    PageResponseVo pageResponseVo = (PageResponseVo) data;
                    List rows = pageResponseVo.getRows();
                    Integer total = pageResponseVo.getTotal();
                    if (total != null && total > 0 && CollectionUtils.isEmpty(rows)) {
                        errorMsg = "数据库异常";
                    }
                }
                if (jsonDataResult.getResult() != 0) {
                    errorMsg = jsonDataResult.getMessage();
                }
            }
            long end = System.currentTimeMillis();
            final String finalErrorMsg = errorMsg;
            // 不能异步
            saveLog(args, end - start, finalErrorMsg);
        }

        return result;
    }


    private void saveLog(Object[] args, long time, String errorMsg) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            String reqMapping = request.getRequestURI().replace(request.getContextPath(), "");
            String polymer = request.getParameter(POLYMER_PARAM);
            String task = request.getParameter(TASK_PARAM);
            AtomicReference<String> serviceCode = new AtomicReference<>("");
            AtomicReference<String> appCode = new AtomicReference<>("");
            boolean commonApiFlag = reqMapping.startsWith(COMMON_API) || reqMapping.startsWith(JSON_COMMON_API);
            if (commonApiFlag) {
                return;
            } else {
                serviceCode.set(request.getParameter(SERVICE_ID));
                appCode.set(request.getParameter(APP_CODE));
            }
            // 当前请求是否缓存到redis
            boolean b = (url.contains(reqMapping))
                    && !POLYMER.equals(polymer)
                    && !TASK_PARAM.equals(task)
                    && StringUtils.isNotEmpty(serviceCode.get())
                    && StringUtils.isNotEmpty(appCode.get());
            if (b) {
                SysPrjservice byServiceCode = sysPrjServiceService.getByServiceCode(serviceCode.get());
                Map<String, String[]> parameterMap = request.getParameterMap();
                ReqLogUtils.cacheLog(byServiceCode, appCode.get(), time, errorMsg, JSONObject.toJSONString(parameterMap), request.getRequestURI());
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

}
